
// Copyright (c) WanSheng Intelligent Corp. All rights reserved.
// Licensed under the LGPL v3.0 license

#define LOG_TAG "s7-module"

#include "s7-plugin.h"

typedef struct S7_HANDLE_DATA_TAG
{
    BROKER_HANDLE broker;
    RESTFUL_CONTEXT restful_context;
    wa_task_scheduler_t task_scheduler;
} S7_HANDLE_DATA;

static int task_s7plc_connect(wa_task_t task)
{
    int i;
    for (i = 0; i < MAX_S7_DEVICE; i++)
    {
        if (g_s7_devices[i] == NULL)
        {
            return 0;
        }

        if (g_s7_devices[i]->dc == NULL)
        {
            open_s7_device(g_s7_devices[i]);
        }
    }
    return 0;
}

static MODULE_HANDLE S7_PLC_Create(BROKER_HANDLE broker, const void *configuration)
{
    S7_HANDLE_DATA *result;
    result = malloc_z(sizeof(S7_HANDLE_DATA));
    if (result != NULL)
    {
        result->broker = broker;
    }
    return result;
}

static void *S7_PLC_ParseConfigurationFromJson(const char *configuration)
{
    return NULL;
}

static void S7_PLC_FreeConfiguration(void *configuration)
{
}

static void S7_PLC_Destroy(MODULE_HANDLE module)
{
    if (module != NULL)
    {
        S7_HANDLE_DATA *moduleHandleData = (S7_HANDLE_DATA *)module;

        if (moduleHandleData->task_scheduler)
            bh_task_destroy_scheduler(moduleHandleData->task_scheduler);

        free(moduleHandleData);
    }
}

static void S7_PLC_Receive(MODULE_HANDLE moduleHandle, MESSAGE_HANDLE messageHandle)
{
}

static void S7_PLC_Start(MODULE_HANDLE module)
{
    S7_HANDLE_DATA *module_data = (S7_HANDLE_DATA *)module;

    RESTFUL_CONTEXT ctx = WA_InitRestful(module_data->broker, module);
    module_data->restful_context = ctx;
    WA_RegisterResource(ctx, "/s7", res_s7_cmd_get_handler, T_Get);
    WA_RegisterResource(ctx, "/s7", res_s7_cmd_put_handler, T_Put);

    // load the configured devices and setup the internal data structure
    const char * plugin_name = WA_GetModuleName(module_data->broker, module);
    load_device_config(plugin_name);

    // start a new thread for handling the tasks
    module_data->task_scheduler = bh_task_run_new_scheduler();

    // create a regular executed task for reconnecting the devices or buses
    wa_task_t task1 = bh_new_task((char *)"connect_task",
                                  NULL,
                                  true,
                                  1 * 2000, // repeating task in 2000 ms
                                  task_s7plc_connect);
    bh_schedule_task(module_data->task_scheduler, task1, 0);
}

/*
 *    Required for all modules:  the public API and the designated implementation functions.
 */
static const MODULE_API_1 S7_PLC_APIS_all =
    {
        {MODULE_API_VERSION_1},

        S7_PLC_ParseConfigurationFromJson,
        S7_PLC_FreeConfiguration,
        S7_PLC_Create,
        S7_PLC_Destroy,
        S7_PLC_Receive,
        S7_PLC_Start};

MODULE_EXPORT const MODULE_API *Module_GetApi(MODULE_API_VERSION gateway_api_version)
{
    // check the SDK version compatibility.
    // Note: the library version in target may be different from the SDK version that this plugin was compiled with.
    if(WA_SDK_INTERFACE_VERSION_CURRENT < wa_sdk_get_interface_version_back())
    {
        printf("HelloWorld: WA_SDK_INTERFACE_VERSION_CURRENT (%d) < framework supported (%d)\n",
            WA_SDK_INTERFACE_VERSION_CURRENT, wa_sdk_get_interface_version_back());
        return NULL;
    }

    (void)gateway_api_version;
    return (const MODULE_API *)&S7_PLC_APIS_all;
}
